﻿using System;
using Constriction.Walls;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Constriction
{
    public class Player
    {
        public const int PLAYER_WIDTH = 32;
        public const int PLAYER_HEIGHT = 32;

        public const int PLAYER_RUN_SPEED = 300;
        public const int PLAYER_JOG_SPEED = 170;
        public const int PLAYER_WALK_SPEED = 100;

        public Rectangle boundedBox;
        public Texture2D tex;

        public WallManager wallManager;

        public bool upPressed, downPressed;
        public bool leftPressed, rightPressed;
        public bool runPressed, walkPressed;

        private Vector2 position;
        private Vector2 velocity;
        private float rotation;

        public Player()
        {
            position = new Vector2(400, 300);
            boundedBox = new Rectangle((int)position.X, (int)position.Y, PLAYER_WIDTH, PLAYER_HEIGHT);
        }

        public void Update(GameTime time)
        {
            HandleInput(time);
            UpdatePosition();
            UpdateBox();
        }

        private void HandleInput(GameTime time)
        {
            velocity = Vector2.Zero;
            int speed;

            if (runPressed)
            {
                speed = PLAYER_RUN_SPEED;
            }
            else if (walkPressed)
            {
                speed = PLAYER_WALK_SPEED;
            }
            else
            {
                speed = PLAYER_JOG_SPEED;
            }

            if (upPressed)
            {
                velocity.Y -= speed;
            }
            if (downPressed)
            {
                velocity.Y += speed;
            }

            if (leftPressed)
            {
                velocity.X -= speed;
            }
            if (rightPressed)
            {
                velocity.X += speed;
            }

            if (velocity != Vector2.Zero)
            {
                rotation = (float)Math.Atan2(velocity.Y, velocity.X);
                velocity.Normalize();

                velocity *= speed * (float)time.ElapsedGameTime.TotalSeconds;
            }
        }

        private void UpdatePosition()
        {
            position.X += velocity.X;
            UpdateBox();

            var solidObstacle = wallManager.IsSpaceFree(this.boundedBox);

            if (solidObstacle.HasValue)
            {
                if (velocity.X > 0)//Right
                {
                    position.X = solidObstacle.Value.Left - PLAYER_WIDTH;
                }
                else if (velocity.X < 0)//Left
                {
                    position.X = solidObstacle.Value.Right;
                }
            }

            position.Y += velocity.Y;
            UpdateBox();
            solidObstacle = wallManager.IsSpaceFree(this.boundedBox);

            if (solidObstacle.HasValue)
            {
                if (velocity.Y > 0)//Down
                {
                    position.Y = solidObstacle.Value.Top - PLAYER_HEIGHT;
                }
                else if (velocity.Y < 0)//Up
                {
                    position.Y = solidObstacle.Value.Bottom;
                }
            }
            
            UpdateBox();
        }

        private void UpdateBox()
        {
            boundedBox.Location = new Point((int)position.X, (int)position.Y);
        }

        public void Draw(SpriteBatch batch)
        {
            float xPos = position.X + PLAYER_WIDTH / 2;
            float yPos = position.Y + PLAYER_HEIGHT / 2;

            batch.Draw(tex, new Vector2(xPos, yPos), null, Color.White, rotation, new Vector2(PLAYER_WIDTH / 2, PLAYER_HEIGHT / 2), 1, SpriteEffects.None, 0);
        }
    }
}
